home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / socks / rftp / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-27  |  9.7 KB  |  515 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)main.c    5.18 (Berkeley) 3/1/91";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  * FTP User Program -- Command Interface.
  46.  */
  47. #include "ftp_var.h"
  48. #include <sys/socket.h>
  49. #include <sys/ioctl.h>
  50. #include <sys/types.h>
  51.  
  52. #include <arpa/ftp.h>
  53.  
  54. #include <signal.h>
  55. #include <stdio.h>
  56. #include <errno.h>
  57. #include <ctype.h>
  58. #include <netdb.h>
  59. #include <pwd.h>
  60.  
  61. uid_t    getuid();
  62. void    intr(), lostpeer();
  63. extern    char *home;
  64. char    *getlogin();
  65.  
  66. main(argc, argv)
  67.     char *argv[];
  68. {
  69.     register char *cp;
  70.     int top;
  71.     struct passwd *pw = NULL;
  72.     char homedir[MAXPATHLEN];
  73.  
  74.     SOCKSinit();
  75.  
  76.     sp = getservbyname("ftp", "tcp");
  77.     if (sp == 0) {
  78.         fprintf(stderr, "ftp: ftp/tcp: unknown service\n");
  79.         exit(1);
  80.     }
  81.     doglob = 1;
  82.     interactive = 1;
  83.     autologin = 1;
  84.     argc--, argv++;
  85.     while (argc > 0 && **argv == '-') {
  86.         for (cp = *argv + 1; *cp; cp++)
  87.             switch (*cp) {
  88.  
  89.             case 'd':
  90.                 options |= SO_DEBUG;
  91.                 debug++;
  92.                 break;
  93.             
  94.             case 'v':
  95.                 verbose++;
  96.                 break;
  97.  
  98.             case 't':
  99.                 trace++;
  100.                 break;
  101.  
  102.             case 'i':
  103.                 interactive = 0;
  104.                 break;
  105.  
  106.             case 'n':
  107.                 autologin = 0;
  108.                 break;
  109.  
  110.             case 'g':
  111.                 doglob = 0;
  112.                 break;
  113.  
  114.             default:
  115.                 fprintf(stdout,
  116.                   "ftp: %c: unknown option\n", *cp);
  117.                 exit(1);
  118.             }
  119.         argc--, argv++;
  120.     }
  121.     fromatty = isatty(fileno(stdin));
  122.     if (fromatty)
  123.         verbose++;
  124.     cpend = 0;    /* no pending replies */
  125.     proxy = 0;    /* proxy not active */
  126.     crflag = 1;    /* strip c.r. on ascii gets */
  127.     sendport = -1;    /* not using ports */
  128.     /*
  129.      * Set up the home directory in case we're globbing.
  130.      */
  131.     cp = getlogin();
  132.     if (cp != NULL) {
  133.         pw = getpwnam(cp);
  134.     }
  135.     if (pw == NULL)
  136.         pw = getpwuid(getuid());
  137.     if (pw != NULL) {
  138.         home = homedir;
  139.         (void) strcpy(home, pw->pw_dir);
  140.     }
  141.     if (argc > 0) {
  142.         if (setjmp(toplevel))
  143.             exit(0);
  144.         (void) signal(SIGINT, intr);
  145.         (void) signal(SIGPIPE, lostpeer);
  146.         setpeer(argc + 1, argv - 1);
  147.     }
  148.     top = setjmp(toplevel) == 0;
  149.     if (top) {
  150.         (void) signal(SIGINT, intr);
  151.         (void) signal(SIGPIPE, lostpeer);
  152.     }
  153.     for (;;) {
  154.         cmdscanner(top);
  155.         top = 1;
  156.     }
  157. }
  158.  
  159. void
  160. intr()
  161. {
  162.  
  163.     longjmp(toplevel, 1);
  164. }
  165.  
  166. void
  167. lostpeer()
  168. {
  169.     extern FILE *cout;
  170.     extern int data;
  171.  
  172.     if (connected) {
  173.         if (cout != NULL) {
  174.             (void) shutdown(fileno(cout), 1+1);
  175.             (void) fclose(cout);
  176.             cout = NULL;
  177.         }
  178.         if (data >= 0) {
  179.             (void) shutdown(data, 1+1);
  180.             (void) close(data);
  181.             data = -1;
  182.         }
  183.         connected = 0;
  184.     }
  185.     pswitch(1);
  186.     if (connected) {
  187.         if (cout != NULL) {
  188.             (void) shutdown(fileno(cout), 1+1);
  189.             (void) fclose(cout);
  190.             cout = NULL;
  191.         }
  192.         connected = 0;
  193.     }
  194.     proxflag = 0;
  195.     pswitch(0);
  196. }
  197.  
  198. /*char *
  199. tail(filename)
  200.     char *filename;
  201. {
  202.     register char *s;
  203.     
  204.     while (*filename) {
  205.         s = rindex(filename, '/');
  206.         if (s == NULL)
  207.             break;
  208.         if (s[1])
  209.             return (s + 1);
  210.         *s = '\0';
  211.     }
  212.     return (filename);
  213. }
  214. */
  215. /*
  216.  * Command parser.
  217.  */
  218. cmdscanner(top)
  219.     int top;
  220. {
  221.     register struct cmd *c;
  222.     register int l;
  223.     struct cmd *getcmd();
  224.     extern int help();
  225.  
  226.     if (!top)
  227.         (void) putchar('\n');
  228.     for (;;) {
  229.         if (fromatty) {
  230.             printf("ftp> ");
  231.             (void) fflush(stdout);
  232.         }
  233.         if (fgets(line, sizeof line, stdin) == NULL)
  234.             quit();
  235.         l = strlen(line);
  236.         if (l == 0)
  237.             break;
  238.         if (line[--l] == '\n') {
  239.             if (l == 0)
  240.                 break;
  241.             line[l] = '\0';
  242.         } else if (l == sizeof(line) - 2) {
  243.             printf("sorry, input line too long\n");
  244.             while ((l = getchar()) != '\n' && l != EOF)
  245.                 /* void */;
  246.             break;
  247.         } /* else it was a line without a newline */
  248.         makeargv();
  249.         if (margc == 0) {
  250.             continue;
  251.         }
  252.         c = getcmd(margv[0]);
  253.         if (c == (struct cmd *)-1) {
  254.             printf("?Ambiguous command\n");
  255.             continue;
  256.         }
  257.         if (c == 0) {
  258.             printf("?Invalid command\n");
  259.             continue;
  260.         }
  261.         if (c->c_conn && !connected) {
  262.             printf("Not connected.\n");
  263.             continue;
  264.         }
  265.         (*c->c_handler)(margc, margv);
  266.         if (bell && c->c_bell)
  267.             (void) putchar('\007');
  268.         if (c->c_handler != help)
  269.             break;
  270.     }
  271.     (void) signal(SIGINT, intr);
  272.     (void) signal(SIGPIPE, lostpeer);
  273. }
  274.  
  275. struct cmd *
  276. getcmd(name)
  277.     register char *name;
  278. {
  279.     extern struct cmd cmdtab[];
  280.     register char *p, *q;
  281.     register struct cmd *c, *found;
  282.     register int nmatches, longest;
  283.  
  284.     longest = 0;
  285.     nmatches = 0;
  286.     found = 0;
  287.     for (c = cmdtab; p = c->c_name; c++) {
  288.         for (q = name; *q == *p++; q++)
  289.             if (*q == 0)        /* exact match? */
  290.                 return (c);
  291.         if (!*q) {            /* the name was a prefix */
  292.             if (q - name > longest) {
  293.                 longest = q - name;
  294.                 nmatches = 1;
  295.                 found = c;
  296.             } else if (q - name == longest)
  297.                 nmatches++;
  298.         }
  299.     }
  300.     if (nmatches > 1)
  301.         return ((struct cmd *)-1);
  302.     return (found);
  303. }
  304.  
  305. /*
  306.  * Slice a string up into argc/argv.
  307.  */
  308.  
  309. int slrflag;
  310.  
  311. makeargv()
  312. {
  313.     char **argp;
  314.     char *slurpstring();
  315.  
  316.     margc = 0;
  317.     argp = margv;
  318.     stringbase = line;        /* scan from first of buffer */
  319.     argbase = argbuf;        /* store from first of buffer */
  320.     slrflag = 0;
  321.     while (*argp++ = slurpstring())
  322.         margc++;
  323. }
  324.  
  325. /*
  326.  * Parse string into argbuf;
  327.  * implemented with FSM to
  328.  * handle quoting and strings
  329.  */
  330. char *
  331. slurpstring()
  332. {
  333.     int got_one = 0;
  334.     register char *sb = stringbase;
  335.     register char *ap = argbase;
  336.     char *tmp = argbase;        /* will return this if token found */
  337.  
  338.     if (*sb == '!' || *sb == '$') {    /* recognize ! as a token for shell */
  339.         switch (slrflag) {    /* and $ as token for macro invoke */
  340.             case 0:
  341.                 slrflag++;
  342.                 stringbase++;
  343.                 return ((*sb == '!') ? "!" : "$");
  344.                 /* NOTREACHED */
  345.             case 1:
  346.                 slrflag++;
  347.                 altarg = stringbase;
  348.                 break;
  349.             default:
  350.                 break;
  351.         }
  352.     }
  353.  
  354. S0:
  355.     switch (*sb) {
  356.  
  357.     case '\0':
  358.         goto OUT;
  359.  
  360.     case ' ':
  361.     case '\t':
  362.         sb++; goto S0;
  363.  
  364.     default:
  365.         switch (slrflag) {
  366.             case 0:
  367.                 slrflag++;
  368.                 break;
  369.             case 1:
  370.                 slrflag++;
  371.                 altarg = sb;
  372.                 break;
  373.             default:
  374.                 break;
  375.         }
  376.         goto S1;
  377.     }
  378.  
  379. S1:
  380.     switch (*sb) {
  381.  
  382.     case ' ':
  383.     case '\t':
  384.     case '\0':
  385.         goto OUT;    /* end of token */
  386.  
  387.     case '\\':
  388.         sb++; goto S2;    /* slurp next character */
  389.  
  390.     case '"':
  391.         sb++; goto S3;    /* slurp quoted string */
  392.  
  393.     default:
  394.         *ap++ = *sb++;    /* add character to token */
  395.         got_one = 1;
  396.         goto S1;
  397.     }
  398.  
  399. S2:
  400.     switch (*sb) {
  401.  
  402.     case '\0':
  403.         goto OUT;
  404.  
  405.     default:
  406.         *ap++ = *sb++;
  407.         got_one = 1;
  408.         goto S1;
  409.     }
  410.  
  411. S3:
  412.     switch (*sb) {
  413.  
  414.     case '\0':
  415.         goto OUT;
  416.  
  417.     case '"':
  418.         sb++; goto S1;
  419.  
  420.     default:
  421.         *ap++ = *sb++;
  422.         got_one = 1;
  423.         goto S3;
  424.     }
  425.  
  426. OUT:
  427.     if (got_one)
  428.         *ap++ = '\0';
  429.     argbase = ap;            /* update storage pointer */
  430.     stringbase = sb;        /* update scan pointer */
  431.     if (got_one) {
  432.         return(tmp);
  433.     }
  434.     switch (slrflag) {
  435.         case 0:
  436.             slrflag++;
  437.             break;
  438.         case 1:
  439.             slrflag++;
  440.             altarg = (char *) 0;
  441.             break;
  442.         default:
  443.             break;
  444.     }
  445.     return((char *)0);
  446. }
  447.  
  448. #define HELPINDENT (sizeof ("directory"))
  449.  
  450. /*
  451.  * Help command.
  452.  * Call each command handler with argc == 0 and argv[0] == name.
  453.  */
  454. help(argc, argv)
  455.     int argc;
  456.     char *argv[];
  457. {
  458.     extern struct cmd cmdtab[];
  459.     register struct cmd *c;
  460.  
  461.     if (argc == 1) {
  462.         register int i, j, w, k;
  463.         int columns, width = 0, lines;
  464.         extern int NCMDS;
  465.  
  466.         printf("Commands may be abbreviated.  Commands are:\n\n");
  467.         for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
  468.             int len = strlen(c->c_name);
  469.  
  470.             if (len > width)
  471.                 width = len;
  472.         }
  473.         width = (width + 8) &~ 7;
  474.         columns = 80 / width;
  475.         if (columns == 0)
  476.             columns = 1;
  477.         lines = (NCMDS + columns - 1) / columns;
  478.         for (i = 0; i < lines; i++) {
  479.             for (j = 0; j < columns; j++) {
  480.                 c = cmdtab + j * lines + i;
  481.                 if (c->c_name && (!proxy || c->c_proxy)) {
  482.                     printf("%s", c->c_name);
  483.                 }
  484.                 else if (c->c_name) {
  485.                     for (k=0; k < strlen(c->c_name); k++) {
  486.                         (void) putchar(' ');
  487.                     }
  488.                 }
  489.                 if (c + lines >= &cmdtab[NCMDS]) {
  490.                     printf("\n");
  491.                     break;
  492.                 }
  493.                 w = strlen(c->c_name);
  494.                 while (w < width) {
  495.                     w = (w + 8) &~ 7;
  496.                     (void) putchar('\t');
  497.                 }
  498.             }
  499.         }
  500.         return;
  501.     }
  502.     while (--argc > 0) {
  503.         register char *arg;
  504.         arg = *++argv;
  505.         c = getcmd(arg);
  506.         if (c == (struct cmd *)-1)
  507.             printf("?Ambiguous help command %s\n", arg);
  508.         else if (c == (struct cmd *)0)
  509.             printf("?Invalid help command %s\n", arg);
  510.         else
  511.             printf("%-*s\t%s\n", HELPINDENT,
  512.                 c->c_name, c->c_help);
  513.     }
  514. }
  515.